//
// Created by 李传智 on 2018/4/12.
//

#include <android/native_window.h>
#include <math.h>
#include "Texture.h"
#include "EGL.h"
#include "Logger.h"
#include "Shader.h"

class Android_Texture : public Texture {

public:
    Shader shader;

    virtual bool init(void *_window, int vWidth, int vHeight, int format) {

        mutex.lock();
        if (!_window) {
            mutex.unlock();
            LOG_I("Android_Texture init failed, window is NULL");
            return false;
        }
        ANativeWindow *window = (ANativeWindow *) _window;
        if (!EGL::get()->init(window)) {
            mutex.unlock();
            return false;
        }

        this->wWidth = ANativeWindow_getWidth(window);
        this->wHeight = ANativeWindow_getHeight(window);
        LOG_D("ANativeWindow: width = %d, height = %d", this->wWidth, this->wHeight);

        float scale = fmax(vWidth * 1.0f / this->wWidth, vHeight * 1.0f / this->wHeight);
        this->dWidth = (int) (vWidth / scale);
        this->dHeight = (int) (vHeight / scale);

        this->dx = (this->wWidth - this->dWidth) / 2;
        this->dy = (this->wHeight - this->dHeight) / 2;
        LOG_D("scale = %f, dx = %d, dy = %d, dWidth = %d ,dHeight = %d", scale, this->dx, this->dy, this->dWidth, this->dHeight);

        this->format = format;
        bool ret = shader.init(format);
        mutex.unlock();

        return ret;
    }

    virtual void draw(unsigned char *data[], int width, int height) {
        mutex.lock();
        // LOG_E("Texture::draw shader(format=%d)", this->format);
        // y
        shader.getTexture(0, width, height, data[0]);
        if (this->format == TEXTURE_YUV420P) {
            // u
            shader.getTexture(1, width / 2, height / 2, data[1]);
            // v
            shader.getTexture(2, width / 2, height / 2, data[2]);
        } else {
            // uv
            shader.getTexture(1, width / 2, height / 2, data[1], true);
        }
        // 绘制
        shader.draw(this->dx, this->dy, this->dWidth, this->dHeight);
        // 绘制到窗口
        EGL::get()->draw();
        mutex.unlock();
    }

    virtual void destroy() {
        mutex.lock();
        EGL::get()->close();
        shader.close();
        mutex.unlock();
        delete this;
    }

};

Texture *Texture::create() {
    return new Android_Texture();
}